package com.dd.cloud.user.util;

import com.dd.cloud.common.utils.SerialNumberUtils;
import com.dd.cloud.user.entity.chknowl.ChknowlBooksCtlg;
import com.dd.cloud.user.service.chknowl.IChknowlBooksCtlgService;
import com.dd.cloud.user.service.chknowl.IChkonwlDoctorBookService;
import com.dd.cloud.user.service.log.ILogErrorService;
import lombok.extern.slf4j.Slf4j;
import nl.siegmann.epublib.domain.*;
import nl.siegmann.epublib.epub.EpubReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;

/**
 * @author xt
 */
@Slf4j
@Component
public class BookUtils {

    @Autowired
    private ILogErrorService errorService;

    @Autowired
    private IChknowlBooksCtlgService chknowlBooksCtlgService;

    private static ILogErrorService errorServiceStatic;

    private static IChknowlBooksCtlgService chknowlBooksCtlgServiceStatic;

    private static String PATH = "bookTemp";

    @PostConstruct
    private void init() {
        errorServiceStatic = this.errorService;
        chknowlBooksCtlgServiceStatic = this.chknowlBooksCtlgService;
    }

    public static void getBookPresentRank(String urlPath, Integer bookId) {
        OutputStream out = null;
        InputStream inputStream = null;
        HttpURLConnection http = null;
        String targetDirectory = PATH + File.separator;
        try {
            // 解决url中可能有中文情况
            System.out.println("url:" + urlPath);
            URL url = new URL(urlPath);
            http = (HttpURLConnection) url.openConnection();
            http.setConnectTimeout(3000);
            // 设置 User-Agent 避免被拦截
            http.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
            String contentType = http.getContentType();
            System.out.println("contentType: " + contentType);
            // 获取文件大小
            long length = http.getContentLengthLong();
            System.out.println("文件大小：" + (length / 1024) + "KB");
            // 获取文件名
            String fileName = getFileName(urlPath);
            File outFile = new File(targetDirectory + fileName);
            String filePath = targetDirectory + fileName;
            System.out.println(filePath);
            if (!outFile.getParentFile().exists()) {
                outFile.getParentFile().mkdirs();
            }
            inputStream = http.getInputStream();
            byte[] buff = new byte[1024 * 10];
            out = new FileOutputStream(new File(targetDirectory, fileName));
            int len;
            int count = 0; // 计数
            while ((len = inputStream.read(buff)) != -1) {
                out.write(buff, 0, len);
                out.flush();
                ++count;
            }
            log.info("count:" + count);
            getBookPresent(new File(filePath), bookId);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //一定要关闭资源
            try {
                if (out != null) {
                    out.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            http.disconnect();
        }
        //删除文件
        PdfToImgUtil.delete(targetDirectory);
    }

    private static String getFileName(String urlPath) throws UnsupportedEncodingException {
        String fileName = null;
        if (null == fileName) {
            // 尝试从url中获取文件名
            String[] arr = urlPath.split("/");
            fileName = arr[arr.length - 1];
            log.info("url中获取文件名：" + fileName);
        }
        return fileName;
    }

    public static void getBookPresent(File file, Integer bookId) {
        InputStream in = null;
        try {
            //从输入流当中读取epub格式文件
            EpubReader reader = new EpubReader();
            in = new FileInputStream(file);
            Book book = reader.readEpub(in);
            //获取到书本的头部信息
            Metadata metadata = book.getMetadata();
            System.out.println("FirstTitle为：" + metadata.getFirstTitle());
            //获取到书本的全部资源
            Resources resources = book.getResources();
            System.out.println("所有资源数量为：" + resources.size());
            //获取所有的资源数据
            Collection<String> allHrefs = resources.getAllHrefs();
            for (String href : allHrefs) {
                Resource resource = resources.getByHref(href);
                //data就是资源的内容数据，可能是css,html,图片等等
                byte[] data = resource.getData();
                // 获取到内容的类型  css,html,还是图片
                MediaType mediaType = resource.getMediaType();
            }
            //获取到书本的内容资源
            List<Resource> contents = book.getContents();
            System.out.println("内容资源数量为：" + contents.size());
            //获取到书本的spine资源 线性排序
            Spine spine = book.getSpine();
            System.out.println("spine资源数量为：" + spine.size());
            //通过spine获取所有的数据
            List<SpineReference> spineReferences = spine.getSpineReferences();
            for (SpineReference spineReference : spineReferences) {
                Resource resource = spineReference.getResource();
                //data就是资源的内容数据，可能是css,html,图片等等
                byte[] data = resource.getData();
                // 获取到内容的类型  css,html,还是图片
                MediaType mediaType = resource.getMediaType();
            }
            //获取到书本的目录资源
            TableOfContents tableOfContents = book.getTableOfContents();
            System.out.println("目录资源数量为：" + tableOfContents.size());
            //获取到目录对应的资源数据
            List<TOCReference> tocReferences = tableOfContents.getTocReferences();
            for (int i = 0; i < tocReferences.size(); i++) {
                String title = tocReferences.get(i).getTitle().trim();
                if ("序".equals(title) || "目录".equals(title) || "封面".equals(title)) {
                    continue;
                }
                digui(tocReferences.get(i), 0, i, 0, bookId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //一定要关闭资源
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void digui(TOCReference tocReference, Integer level, Integer sort, Integer pid, Integer bookId) {
        level++;
        String title = tocReference.getTitle();
        log.info("第" + level + "层,章节名为:{}" + title + ",父级pid:" + pid + ",次层排序为:" + sort);
        //处理业务代码 保存 不想使用自己生成的主键 所以一条条添加 后续走异步
        saveBookCtlg(bookId, title, level, pid, sort);
        if (tocReference.getChildren().size() > 0) {
            //获取子目录的内容
            List<TOCReference> children = tocReference.getChildren();
            for (int i = 0; i < children.size(); i++) {
                digui(children.get(i), level, i, pid, bookId);
            }
        }
    }

    private static Integer saveBookCtlg(Integer bookId, String title, int level, int pid, int sort) {
        ChknowlBooksCtlg chknowlBooksCtlg = new ChknowlBooksCtlg();
        chknowlBooksCtlg.setBookId(bookId).setRank(level).setName(title).setStatus(1).setPid(pid).setSort(sort).setCreateDate(LocalDateTime.now());
        Boolean flag = chknowlBooksCtlgServiceStatic.save(chknowlBooksCtlg);
        if (!flag) {
            log.info("保存书籍目录失败！");
            errorServiceStatic.presBackLog("保存书籍目录失败", "保存书籍目录递归失败", "书籍id:" + bookId);
        }
        return chknowlBooksCtlg.getId();
    }

}
